package com.telit.android.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.telit.android.dao.AppPatrolTrackDao;
import com.telit.android.entity.AppPatrolTrack;
import com.telit.android.service.TaskHomeService;
import com.telit.common.constant.RoleCodeConstants;
import com.telit.common.core.utils.FeignUtils;
import com.telit.common.dto.PatrolAndCruiseCountDTO;
import com.telit.common.entity.DataReturn;
import com.telit.common.entity.PageData;
import com.telit.common.enums.ResultCode;
import com.telit.common.exception.ForestBaseException;
import com.telit.common.util.HandleStrUtils;
import com.telit.common.util.LanguageUtils;
import com.telit.common.util.TimeUtils;
import com.telit.firecommand.feign.RemoteFirecommandService;
import com.telit.firecommand.vo.ForesterVO;
import com.telit.uav.feign.RemoteUavService;
import com.telit.upms.dto.DynamicParamsForQueryUserDto;
import com.telit.upms.feign.RemoteUpmsService;
import com.telit.upms.vo.MicroSysDistrictVo;
import com.telit.upms.vo.MicroSysUserAllInfoVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


/**
 * @Auther amy
 * @Describe
 */
@Service
public class TaskHomeServiceImpl implements TaskHomeService {

    @Autowired
    private AppPatrolTrackDao appPatrolTrackDao;

    @Autowired
    private RemoteUpmsService upmsService;

    @Autowired
    private RemoteFirecommandService remoteFirecommandService;


    @Autowired
    private RemoteUavService uavService;


    @Override
    public Map<String, Object> patrolAndCruiseInfoCount() {
        Integer cruiseCount = 0;
        String cruiseDistance = StringUtil.EMPTY;
        String cruiseDuration = StringUtil.EMPTY;
        String flyArea = StringUtil.EMPTY;
        Map<String, Object> resultMap = new HashMap<>();
        // 巡护总次数 巡护总时长(小时)  巡护总公里数(公里)
        PatrolAndCruiseCountDTO patrolCountDTO = appPatrolTrackDao.selectPatrolCountInfo();
        resultMap.put("patrolCount", patrolCountDTO.getCount());
        resultMap.put("patrolDistance", HandleStrUtils.handlerDistanceToKm(patrolCountDTO.getDistance())); // 距离 千米
        resultMap.put("patrolDuration", TimeUtils.secondsToHour(patrolCountDTO.getDuration()));// 时长 小时

        // 巡航总次数 飞行总时长(小时)  飞行总公里数(公里) 飞行总面积(平方公里)
        DataReturn dataReturn = uavService.cruiseTrackInfo();
        if (dataReturn != null && dataReturn.getData() != null) {
            PatrolAndCruiseCountDTO cruiseCountDTO = JSON.parseObject(JSON.toJSONString(dataReturn.getData()),
                    PatrolAndCruiseCountDTO.class);
            if (cruiseCountDTO != null) {
                cruiseCount = cruiseCountDTO.getCount();
                cruiseDistance = HandleStrUtils.handlerDistanceToKm(cruiseCountDTO.getDistance());
                cruiseDuration = TimeUtils.secondsToHour(cruiseCountDTO.getDuration());
                flyArea = cruiseCountDTO.getFlyArea();
            }
        }

        resultMap.put("cruiseCount", cruiseCount);
        resultMap.put("cruiseDistance", cruiseDistance);
        resultMap.put("cruiseDuration", cruiseDuration);
        resultMap.put("flyArea", flyArea);
        return resultMap;
    }

    @Override
    public Map<String, Object> patrolAndCruiseInfoCountForNew(String districtCode) {
        final Map<String, Object> resultMap = Maps.newHashMap();
        resultMap.put("patrolCount", BigDecimal.ZERO.intValue());
        resultMap.put("patrolDistance", BigDecimal.ZERO.toPlainString()); // 距离 千米
        resultMap.put("patrolDuration", BigDecimal.ZERO.toPlainString());// 时长 小时
        resultMap.put("cruiseCount", BigDecimal.ZERO.intValue());
        resultMap.put("cruiseDistance", BigDecimal.ZERO.toPlainString());
        resultMap.put("cruiseDuration", BigDecimal.ZERO.toPlainString());
        resultMap.put("flyArea", BigDecimal.ZERO.toPlainString());

//        //根据行政区划code 查询 该code 和 code 下有多少用户
//        final List<Long> userIds = fireMangerIdListByDistrictCode(districtCode);
        //根据名称查询人员
        DataReturn<PageData<List<ForesterVO>>> qryUserListDataReturn = remoteFirecommandService.qryUserList(null, null,
                districtCode, true, null, null, 1, Integer.MAX_VALUE);
        if (!ResultCode.SUCCESS.getCode().equals(qryUserListDataReturn.getCode())) {
            throw new ForestBaseException(qryUserListDataReturn.getErrorMsg());
        }
        List<Long> userIds = qryUserListDataReturn.getData().getDatas().stream().map(
                foresterVO -> Convert.toLong(foresterVO.getId())).collect(Collectors.toList());

        //如果userId 查询出的为空返回0
        if (CollUtil.isEmpty(userIds)) {
            return resultMap;
        }

        //巡护统计（需要和巡护记录的时长和距离保持一致）
        final IPage<AppPatrolTrack> pages = appPatrolTrackDao.queryPatrolTrackRecordWithFuzzyName(
                new Page<>(1, Integer.MAX_VALUE), userIds, null, null);
        AtomicReference<Integer> patrolCount = new AtomicReference<>(0);
        AtomicReference<BigDecimal> distance = new AtomicReference<>(new BigDecimal(0));
        AtomicReference<BigDecimal> duration = new AtomicReference<>(new BigDecimal(0));
        pages.getRecords().forEach(e -> {
            patrolCount.getAndSet(patrolCount.get() + 1);
            long between = DateUtil.between(e.getStartTime(), e.getEndTime(), DateUnit.MINUTE);
            duration.getAndSet(duration.get().add(new BigDecimal(between)));
            distance.getAndSet(distance.get().add(NumberUtil.roundHalfEven(
                    NumberUtil.toBigDecimal(e.getDistance()).divide(NumberUtil.toBigDecimal("1000")), 3)));
        });
//        final PatrolAndCruiseCountDTO patrolAndCruiseCountDTO = appPatrolTrackDao.selectPatrolCountInfoByUserIds(
//                userIds);
        resultMap.put("patrolCount", patrolCount.get());
        resultMap.put("patrolDistance", distance.get()); // 距离 千米
        DecimalFormat df = new DecimalFormat("0.000");
        resultMap.put("patrolDuration", duration.get().divide(new BigDecimal(60), 3, BigDecimal.ROUND_HALF_UP));// 时长 小时

        // 巡护总次数 巡护总时长(小时)  巡护总公里数(公里)
        final DataReturn dataReturn = uavService.cruiseTrackInfoByUserId(userIds);
        //巡航总次数单独查询，与飞行记录数量保持一致
        final DataReturn dataReturnCruiseCount = uavService.selectcountByUserId(userIds);
        if (dataReturn != null && dataReturn.getData() != null && dataReturnCruiseCount != null) {
            PatrolAndCruiseCountDTO cruiseCountDTO = JSON.parseObject(JSON.toJSONString(dataReturn.getData()),
                    PatrolAndCruiseCountDTO.class);
            PatrolAndCruiseCountDTO cruiseCount = JSON.parseObject(JSON.toJSONString(dataReturnCruiseCount.getData()),
                    PatrolAndCruiseCountDTO.class);
            if (cruiseCountDTO != null) {
//                resultMap.put("cruiseCount", cruiseCountDTO.getCount());
                //巡航总次数做修改，与飞行记录数量保持一致
                resultMap.put("cruiseCount", cruiseCount.getCount());
                resultMap.put("cruiseDistance", HandleStrUtils.handlerDistanceToKm(cruiseCountDTO.getDistance()));
                resultMap.put("cruiseDuration", TimeUtils.secondsToHour(cruiseCountDTO.getDuration()));
                resultMap.put("flyArea", cruiseCountDTO.getFlyArea());
            }
        }
        return resultMap;
    }


    private List<Long> fireMangerIdListByDistrictCode(String districtCode) {
        //通过多维度code查询对应人员信息发送消息
        List<String> codes = new ArrayList<>();
        if (StringUtils.isNotBlank(districtCode)) {
            codes.add(districtCode);
            if (districtCode.length() > 6) {
                codes.add(districtCode.substring(0, 6));
                codes.add(districtCode.substring(0, 4));
            }
        }
        //根据行政区划编码查询行政区划ID
        com.telit.common.core.utils.Result<Map<String, MicroSysDistrictVo>> selectDistrictDetailByListCodesResult = upmsService.selectDistrictDetailByListCodes(
                codes);
        Map<String, MicroSysDistrictVo> microSysDistrictVoMap = FeignUtils.unwrap(
                selectDistrictDetailByListCodesResult);
        List<Long> areaIds = new ArrayList<>();
        for (String code : codes) {
            MicroSysDistrictVo microSysDistrictVo = microSysDistrictVoMap.get(code);
            if (microSysDistrictVo == null) {
                throw new ForestBaseException(LanguageUtils.codeMessage(ResultCode.OPERATE_ERROR.getCode()));
            }
            areaIds.add(microSysDistrictVo.getId());

        }
        List<Long> userLists = new ArrayList<>();
        for (Long areaId : areaIds) {
            DynamicParamsForQueryUserDto dynamicParamsForQueryUserDto = DynamicParamsForQueryUserDto.builder()
                    .page(JSONUtil.toJsonStr(new Page<>(1, 100)))
                    .roleId(RoleCodeConstants.ROLE_CODE_FIRE_MANAGER_ID)//2023-01-10：由于统一平台不支持通过角色码查询，只能固定角色ID查询
                    .areaId(areaId)//行政区划Id
                    .areaRecursion(false)//是否开启行政区划递归往下搜索
                    .build();
            com.telit.common.core.utils.Result<Page<MicroSysUserAllInfoVo>> selectUserContainDeptAndRoleForPageSupportOrderResult = upmsService.selectUserContainDeptAndRoleForPageSupportOrder(
                    dynamicParamsForQueryUserDto);
            Page<MicroSysUserAllInfoVo> microSysUserAllInfoVoPage = FeignUtils.unwrap(
                    selectUserContainDeptAndRoleForPageSupportOrderResult);

            microSysUserAllInfoVoPage.getRecords().stream()
                    .forEach(microSysUserAllInfoVo -> {
                        userLists.add(microSysUserAllInfoVo.getId());
                    });

        }
        return userLists;
    }


}
